#include "widget.h"
#include "ui_widget.h"

VideoCapture cap;
bool cap_flag;
//global variable
extern QMutex upper_frame_mutex;
extern QMutex upper_cap_mutex;
extern QMutex cap_mutex;
QMutex readPictMutex;

#define CameraWidht    1280
#define CameraHeight   720

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    button_flag = false;//按钮状态
    cap_flag = false;//摄像头状态
    /* 设置窗口 */
    rect = QRect(0,0,ShowWindowSizeWidht,ShowWindowSizeHeight);
    view = new QGraphicsView(this);
    scene= new QGraphicsScene(view);
    view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//关闭上下滚动条
    view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//关闭左右滚动条
    view->setGeometry(rect);
    scene->setSceneRect(rect);
    scene->addItem(&item);
    view->setScene(scene);

    ui->contain->move(this->size().width()-ui->contain->size().width()-2,2);

    connect(&thread,SIGNAL(isready(Mat*)),this,SLOT(getCameraFrame(Mat*)));
    connect(&socket,SIGNAL(readyRead()),this,SLOT(readReadySlot()));//客户端有缓冲区时，会触发readyRead()

}

bool sendFlag=true;
Mat dst;
void Widget::getCameraFrame(Mat *frame)
{
    upper_frame_mutex.lock();
    //cvtColor(*frame,dst,COLOR_BGR2GRAY);
    frame->copyTo(dst);
    send_image = Mat2QImage(dst);//Mat转QImage
    upper_frame_mutex.unlock();

    send_image = send_image.scaled(ShowWindowSizeWidht, ShowWindowSizeHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//缩放
    item.setPixmap(QPixmap::fromImage(send_image));

    if(sendFlag && button_flag)
    {
        sendPicture();
        sendFlag=false;
    }
}
static bool once=true;
void Widget::sendPicture()
{
    upper_frame_mutex.lock();
    imwrite("/home/pi/code/picture/send.jpg",dst);
    upper_frame_mutex.unlock();

    if(button_flag){
        if(once){
            socket.write("start");
            while(!socket.waitForBytesWritten());
            once = false;
        }else{
            dataArray = "/home/pi/code/picture/send.jpg";
            quint32 write_len = socket.write(dataArray);

            //qDebug()<<"write_len ="<<write_len;
            while(!socket.waitForBytesWritten());
        }
    }
}

void Widget::readReadySlot()
{    
    QString receive= socket.readAll();
    //qDebug()<<"clien receive data ="<<receive;
    if(receive == "OK")
    {
        sendPicture();
    }
}

void Widget::on_pushButton_clicked()
{
    if(button_flag){
        ui->pushButton->setText("连接服务器");
        button_flag = false;
        closeCamera();
        //此时是断开状态
    }
    else{
        //此时是连接状态
        serverIP = ui->serverip_ui->text();//服务器ip
        serverPort = ui->serverport_ui->text().toInt();//服务器port
        socket.connectToHost(serverIP,serverPort);
        if(!socket.waitForConnected(3000))//连接失败，返回false
        {
            QMessageBox::about(this,"错误","连接超时");
            return;
        }
        ui->pushButton->setText("断开连接");
        button_flag = true;
        openCamera();
    }
}

void Widget::openCamera()
{
    /* 打开摄像头 */
    VideoWriter upper_writer;
    cap.open("/dev/v4l/by-path/platform-fe3c0000.usb-usb-0:1:1.0-video-index0");//打开摄像头
    if(!cap.isOpened())
    {
        QMessageBox::information(NULL, "Camera0", "Open Error");
        exit(-1);
    }
    cap.set(CAP_PROP_FOURCC, upper_writer.fourcc('M','J','P','G'));//视频流格式,MJPEG 的工作是将 RGB 格式的影像转换成 YCrCB 格式，目的是为了减少档案大小，一般约可减少 1/3 ~ 1/2 左右）
    cap.set(CAP_PROP_FRAME_WIDTH, CameraWidht); //帧宽
    cap.set(CAP_PROP_FRAME_HEIGHT, CameraHeight);//帧高

#ifdef DEBUG
    /* 检查摄像头是否支持设定的分辨率格式 */
    qDebug() << "GET_Upper_WIDTH"<<cap.get(CAP_PROP_FRAME_WIDTH);
    qDebug() << "GET_Upper_HEIGHT"<<cap.get(CAP_PROP_FRAME_HEIGHT);
#endif
    cap_flag = true;
    thread.start();//开始采集
}

void Widget::closeCamera()
{
    /* 关闭摄像头 */
    cap_mutex.lock();
    cap.release();
    cap_mutex.unlock();
    cap_flag = false;
}

Widget::~Widget()
{
    delete ui;
    socket.disconnectFromHost();
    socket.waitForDisconnected();
}
/* #########################  以下是稳定代码 ######################################### */
/*************************** 下面是QImge 和 Mat转换代码  *******************************/
/* Mat转 QImage*/
QImage Widget::Mat2QImage(const cv::Mat& mat)
{
    if(mat.type() == CV_8UC1)
    {
        //cout << "CV_8UC1 "<<endl;
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        image.setColorCount(256);
        for(int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++)
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }
    else if(mat.type() == CV_8UC3)
    {
        //cout << "CV_8UC3 "<<endl;
        const uchar *pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return image.rgbSwapped();
    }
    else if(mat.type() == CV_8UC4)
    {
        //cout << "CV_8UC4 "<<endl;
        const uchar *pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image.copy();
    }
    else
    {
        //cout << "CV_8UC5 "<<endl;
        return QImage();
    }
}

/* QImage转Mat */
Mat Widget::QImage2Mat(QImage image)
{
    cv::Mat mat;

    if(QImage::Format_ARGB32 == image.format() || QImage::Format_RGB32 == image.format() || QImage::Format_ARGB32_Premultiplied == image.format())
    {
        mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
    }
    else if(QImage::Format_RGB888 == image.format())
    {
        mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
        cv::cvtColor(mat, mat, COLOR_BGR2RGB);
    }
    else if(QImage::Format_Indexed8 == image.format())
    {
        mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
    }
    return mat;
}

